package cn.ug.pay.component;

import cn.ug.account.bean.DataDictionaryBean;
import cn.ug.analyse.bean.request.MemberAnalyseMsgParamBean;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.FundRateConfig;
import cn.ug.config.RedisGlobalLock;
import cn.ug.config.YeePayConfig;
import cn.ug.core.ensure.Ensure;
import cn.ug.enums.PayTypeEnum;
import cn.ug.enums.RateKeyEnum;
import cn.ug.enums.WxTemplateEnum;
import cn.ug.feign.*;
import cn.ug.mall.bean.MemberGoodsOrderDetailBean;
import cn.ug.mall.bean.OrderBean;
import cn.ug.msg.bean.type.SmsType;
import cn.ug.msg.mq.Msg;
import cn.ug.msg.mq.Sms;
import cn.ug.msg.mq.WxMessageParamBean;
import cn.ug.msg.mq.WxNotifyData;
import cn.ug.pay.bean.BillBean;
import cn.ug.pay.bean.ProductOrderBean;
import cn.ug.pay.bean.WithdrawAuditBean;
import cn.ug.pay.bean.request.TradeCommonParamBean;
import cn.ug.pay.bean.request.YeePayParamBean;
import cn.ug.pay.bean.response.ExtractGoldBaseBean;
import cn.ug.pay.bean.status.CommonConstants;
import cn.ug.pay.bean.status.PayDistributePrefix;
import cn.ug.pay.bean.status.TbillStatusEnum;
import cn.ug.pay.bean.type.BillType;
import cn.ug.pay.bean.type.ProductOrderPayStatus;
import cn.ug.pay.bean.type.TradeType;
import cn.ug.pay.bean.type.WithdrawStatus;
import cn.ug.pay.mapper.*;
import cn.ug.pay.mapper.entity.*;
import cn.ug.pay.pay.yeepay.TZTService;
import cn.ug.pay.service.*;
import cn.ug.pay.utils.RequestUtil;
import cn.ug.product.bean.response.ProductFindBean;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.DateUtils;
import cn.ug.util.UF;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;

import static cn.ug.config.QueueName.*;
import static cn.ug.util.ConstantUtil.GOLD_WEIGHT_RANGE;

/**
 * 易宝支付公共方法(绑卡、支付、提现)
 */
@Component
public class YeePayCommons implements Serializable{
    @Autowired
    private RateSettingsService rateSettingsService;
    @Resource
    private ProductOrderService productOrderService;
    @Autowired
    private ProductOrderFeeMapper productOrderFeeMapper;
    @Resource
    private BillService billService;
    @Autowired
    private CouponRepertoryService couponRepertoryService;
    @Resource
    private WithdrawService withdrawService;
    @Autowired
    private ProductService productService;
    @Autowired
    private DataDictionaryService dataDictionaryService;
    @Resource
    private MallGoodsOrderService mallGoodsOrderService;
    @Autowired
    private PriceService priceService;
    @Resource
    private MemberAccountService memberAccountService;

    @Resource
    private TradeMapper tradeMapper;
    @Autowired
    private FundRateConfig fundRateConfig;
    @Resource
    private MemberAccountMapper memberAccountMapper;

    @Resource
    private AmqpTemplate amqpTemplate;
    @Autowired
    private MemberGoldMapper memberGoldMapper;
    @Resource
    private RedisGlobalLock redisGlobalLock;

    @Resource
    private YeePayConfig yeePayConfig;

    @Resource
    private RequestUtil requestUtil;

    @Resource
    private TZTService tZTService;
    @Autowired
    private OrderService orderService;
    @Resource
    private DozerBeanMapper dozerBeanMapper;
    @Autowired
    private BillMapper billMapper;
    @Autowired
    private PayTbillMapper payTbillMapper;
    @Autowired
    private PayTbillService payTbillService;

    @Resource
    private EntityExtractGoldMapper entityExtractGoldMapper;
    @Resource
    private ExtractionGoldService extractionGoldService;

    @Resource
    private ExtractionOfflineMapper extractionOfflineMapper;

    private static Logger logger = LoggerFactory.getLogger(YeePayCommons.class);

    /**
     * 公共支付请求
     * @param entity
     * @return
     */
    public Map<String,Object> prepayOrder(TradeCommonParamBean entity){
        Map<String,Object> resultMap = new HashMap<String,Object>();
        //组装
        entity.setCallBackUrl(yeePayConfig.getPayCallBackUrl());
        TreeMap<String, String> dataMap = requestUtil.getRequestParam(entity);
        logger.info("---支付请求参数---"+dataMap.toString());
        //发起请求
        Map<String,String> map = requestUtil.sendYeePayHttp(yeePayConfig.getUnSendBindPayRequestURL(),dataMap);
        logger.info("--支付请求返回参数--"+map);
        if(map != null && !map.isEmpty()){
            if(map.containsKey("status")){
                String status = String.valueOf(map.get("status"));
                Trade trade = new Trade();
                trade.setSerialNumber(entity.getOrderId());
                //处理中
                if("PROCESSING".equals(status)){
                    trade.setStatus(CommonConstants.PayStatus.PROCESSING.getIndex());
                    trade.setThirdNumber(map.get("yborderid"));
                    logger.info("-----交易处理中-----订单号:"+entity.getOrderId());

                    //获取账户
                    MemberAccount memberAccount = memberAccountMapper.findByMemberId(entity.getMemberId());
                    BigDecimal changeAmount = entity.getPayAmount().subtract(entity.getAmount());   //变动金额--冻结金额
                    //锁定账户余额
                    Map<String,Object>  param = new HashMap<String,Object>();
                    param.put("id", memberAccount.getId());
                    param.put("freezeAmount", memberAccount.getFreezeAmount().add(changeAmount));
                    param.put("usableAmount", memberAccount.getUsableAmount().subtract(changeAmount));
                    logger.info("----map---"+param);
                    memberAccountMapper.updateByPrimaryKeySelective(param);
                    if (PayTypeEnum.GOLD_EXTRACTION.getType() == entity.getType() || PayTypeEnum.GOLD_CHANGE.getType() == entity.getType() ||
                            PayTypeEnum.MALL_NEW.getType() == entity.getType()) {
                        orderService.handling(trade.getSerialNumber());
                    }
                }else if("FAIL".equals(status)){
                    trade.setStatus(CommonConstants.PayStatus.PROCESSING.getIndex());
                    trade.setThirdNumber(map.get("yborderid"));
                    logger.info("-----交易处理中-----订单号:"+entity.getOrderId());

                    //获取账户
                    MemberAccount memberAccount = memberAccountMapper.findByMemberId(entity.getMemberId());
                    BigDecimal changeAmount = entity.getPayAmount().subtract(entity.getAmount());   //变动金额--冻结金额
                    //锁定账户余额
                    Map<String,Object>  param = new HashMap<String,Object>();
                    param.put("id", memberAccount.getId());
                    param.put("freezeAmount", memberAccount.getFreezeAmount().add(changeAmount));
                    param.put("usableAmount", memberAccount.getUsableAmount().subtract(changeAmount));
                    logger.info("----map---"+param);
                    memberAccountMapper.updateByPrimaryKeySelective(param);
                    if (PayTypeEnum.GOLD_EXTRACTION.getType() == entity.getType() || PayTypeEnum.GOLD_CHANGE.getType() == entity.getType() ||
                            PayTypeEnum.MALL_NEW.getType() == entity.getType()) {
                        orderService.handling(trade.getSerialNumber());
                    } else if (PayTypeEnum.TBILL.getType() == entity.getType()) {
                        PayTbill payTbill = payTbillMapper.selectByOrderNO(trade.getSerialNumber());
                        if (payTbill != null && StringUtils.isNotBlank(payTbill.getCouponId())) {
                            couponRepertoryService.unlock(payTbill.getCouponId());
                        }
                        if (payTbill != null && StringUtils.isNotBlank(payTbill.getTicketId())) {
                            couponRepertoryService.unlock(payTbill.getTicketId());
                        }
                    }
                }else{
                    //失败
                    trade.setStatus(CommonConstants.PayStatus.FAIL.getIndex());
                    trade.setDescription(map.get("errormsg"));
                    trade.setErrCode(map.get("errorcode"));
                    resultMap.put("msg",map.get("errormsg"));
                    //错误码
                    resultMap.put("errorcode",map.get("errorcode"));

                    logger.info("----交易失败trade信息---" + JSONObject.toJSONString(trade));
                    if(CommonConstants.PayType.BUYING.getIndex() == entity.getType() || CommonConstants.PayType.RECHARGE.getIndex() == entity.getType()){
                        Trade trades = tradeMapper.queryTradeBySerialNumber(trade.getSerialNumber());
                        if(CommonConstants.PayStatus.YESPAY.getIndex() != trades.getStatus()){
                            productOrderService.updatePayStatus(ProductOrderPayStatus.FAIL.getValue(),trade.getSerialNumber());
                            ProductOrderFee productOrderFee = productOrderFeeMapper.findByOrderId(trade.getSerialNumber());
                            if(null != productOrderFee) {
                                if(StringUtils.isNotBlank(productOrderFee.getCouponRedId())) {
                                    couponRepertoryService.unlock(productOrderFee.getCouponRedId());
                                }
                                if(StringUtils.isNotBlank(productOrderFee.getCouponIncreaseId())) {
                                    couponRepertoryService.unlock(productOrderFee.getCouponIncreaseId());
                                }
                            }
                        }
                    }else if(CommonConstants.PayType.MALL.getIndex() == entity.getType()){
                        SerializeObject<MemberGoodsOrderDetailBean> mallObj = mallGoodsOrderService.getOrderDetail(trade.getSerialNumber());
                        if(mallObj.getCode() == ResultType.NORMAL){
                            MemberGoodsOrderDetailBean goodsOrder = mallObj.getData();
                            if(goodsOrder.getStatus() ==1){
                                mallGoodsOrderService.failOrder(trade.getSerialNumber(), map.get("errormsg"));
                            }
                        }else{
                            Ensure.that(true).isTrue("17000416");
                        }
                    } else if (PayTypeEnum.GOLD_EXTRACTION.getType() == entity.getType() || PayTypeEnum.GOLD_CHANGE.getType() == entity.getType() ||
                            PayTypeEnum.MALL_NEW.getType() == entity.getType()) {
                        orderService.fail(trade.getSerialNumber(), map.get("errormsg"));

                    }else if (PayTypeEnum.ENTITY_GOLD_EXTRACTION.getType() == entity.getType()){
                        Trade trades = tradeMapper.queryTradeBySerialNumber(trade.getSerialNumber());
                        if(CommonConstants.PayStatus.YESPAY.getIndex() != trades.getStatus()){
                            Map<String, Object> param = new HashMap<String, Object>();
                            param.put("orderNo", trade.getSerialNumber());
                            //设置快递提金表  提金状态 0.交易失败
                            param.put("status", 0);
                            param.put("remark",map.get("errormsg"));
                            entityExtractGoldMapper.update(param);
                            //微信推送
                            extractionGoldService.wxCloseSend(trade.getMemberId(),"支付失败");
                        }
                    }else if (PayTypeEnum.EXTRACTION_OFFLINE.getType() == entity.getType()){
                        Trade trades = tradeMapper.queryTradeBySerialNumber(trade.getSerialNumber());
                        if(CommonConstants.PayStatus.YESPAY.getIndex() != trades.getStatus()){
                            Map<String, Object> param = new HashMap<String, Object>();
                            param.put("orderNo", trade.getSerialNumber());
                            //设置门店提金表  提金状态 0.交易失败
                            param.put("status", 0);
                            param.put("remark",map.get("errormsg"));
                            extractionOfflineMapper.update(param);
                            //微信推送
                            extractionGoldService.wxCloseSend(trade.getMemberId(),"支付失败");
                        }
                    } else if (PayTypeEnum.TBILL.getType() == entity.getType()) {
                        Trade trades = tradeMapper.queryTradeBySerialNumber(trade.getSerialNumber());
                        logger.info("----交易失败trades信息---" + JSONObject.toJSONString(trades));
                        if(CommonConstants.PayStatus.YESPAY.getIndex() != trades.getStatus()){
                            Map<String, Object> param = new HashMap<String, Object>();
                            param.put("orderNO", trade.getSerialNumber());
                            param.put("status", TbillStatusEnum.FAIL.getStatus());
                            param.put("modifyTime", UF.getFormatDateTime(UF.getDateTime()));
                            param.put("readed", 0);
                            payTbillMapper.update(param);
                            PayTbill payTbill = payTbillMapper.selectByOrderNO(trade.getSerialNumber());
                            logger.info("----交易失败payTbill信息---" + JSONObject.toJSONString(payTbill));
                            if (payTbill != null && StringUtils.isNotBlank(payTbill.getCouponId())) {
                                couponRepertoryService.unlock(payTbill.getCouponId());
                            }
                            if (payTbill != null && StringUtils.isNotBlank(payTbill.getTicketId())) {
                                couponRepertoryService.unlock(payTbill.getTicketId());
                            }
                            if (payTbill != null && payTbill.getBeans() > 0) {
                                MemberAccount memberAccount = memberAccountMapper.findByMemberId(payTbill.getMemberId());
                                logger.info("----交易失败memberAccount信息---" + JSONObject.toJSONString(memberAccount));
                                if (memberAccount != null) {
                                    Map<String,Object> accountMap = new HashMap<String,Object>();
                                    accountMap.put("id",memberAccount.getId());
                                    accountMap.put("totalBean", memberAccount.getTotalBean()+payTbill.getBeans());
                                    accountMap.put("usableBean", memberAccount.getUsableBean()+payTbill.getBeans());
                                    memberAccountMapper.updateByPrimaryKeySelective(accountMap);
                                }
                            }
                        }
                    }
                    logger.info("----订单关闭----orderId="+trade.getSerialNumber());
                    logger.info("-----交易失败-----订单号:"+entity.getOrderId()+",-----status:"+status+",-----errormsg"+map.get("errormsg"));
                }
                trade.setAmount(entity.getPayAmount());
                trade.setPayAmount(entity.getAmount());
                tradeMapper.updatePayStatus(trade);
                logger.info("----支付更新订单状态完成---");
            }else{
                //提示错误原因
                Ensure.that(true).isTrue(map.get("customError"));
            }
        }
        return resultMap;
    }

    /**
     * 公共异步回调接口
     * @param yeePayParamBean
     * @return
     */
    public String yeePayAsyNotify(YeePayParamBean yeePayParamBean) {
        logger.info("merchantno="+yeePayParamBean.getMerchantno()+",key="+yeePayParamBean.getEncryptkey()+",data"+yeePayParamBean.getData());
        //将实体转化成Map
        Map<String, String>	result	= tZTService.decryptCallbackData(yeePayParamBean.getData(), yeePayParamBean.getEncryptkey());
        logger.info("-----易宝支付异步返回参数----"+result.toString());
        if(!result.containsKey("customError")){
            String status = result.get("status");
            String serialNumber = result.get("requestno");
            String thirdNumber = result.get("yborderid");
            String amount = result.get("amount");

            //验证该订单号是否支付完成
            Trade trade = tradeMapper.queryTradeBySerialNumber(serialNumber);
            Ensure.that(trade == null).isTrue("17000420");
            if(trade.getStatus() != CommonConstants.PayStatus.YESPAY.getIndex()){
                //更新交易数据
                Trade trades = new Trade();
                trades.setSerialNumber(serialNumber);
                trades.setThirdNumber(thirdNumber);
                //支付成功
                if("PAY_SUCCESS".equals(status)){
                    trades.setStatus(CommonConstants.PayStatus.YESPAY.getIndex());
                    BigDecimal rechargeAmount = new BigDecimal(amount);
                    BigDecimal fundAmount = BigDecimal.ZERO;
                    // 1、获取分布式锁防止重复调用 =====================================================
                    String key = PayDistributePrefix.PAY_MEMBER_ACCOUNT + trade.getMemberId();
                    if(redisGlobalLock.lock(key)) {
                        try{
                            //获取账户
                            MemberAccount memberAccount = memberAccountMapper.findByMemberId(trade.getMemberId());
                            fundAmount = memberAccount.getFundAmount();

                            //账户资金
                            if(trade.getAmount().compareTo(rechargeAmount) != 0){
                                BigDecimal payFreezeAmount = trade.getAmount().subtract(rechargeAmount); //计算账户余额金额=交易总金额-实际支付金额
                                fundAmount = memberAccount.getFundAmount().subtract(payFreezeAmount);  //账户总金额=账户总额-余额支付金额
                                BigDecimal freezeAmount = memberAccount.getFreezeAmount().subtract(payFreezeAmount);  //冻结金额=账户冻结金额-余额支付金额

                                logger.info("---日志操作-----payFreezeAmount="+payFreezeAmount+"------fundAmount-----="+fundAmount+"---rechargeAmount----"+rechargeAmount);
                                Map<String,Object>  param = new HashMap<String,Object>();
                                param.put("id", memberAccount.getId());
                                param.put("fundAmount", fundAmount);
                                param.put("freezeAmount", freezeAmount);
                                memberAccountMapper.updateByPrimaryKeySelective(param);
                                logger.info("----支付异步账户扣款成功---"+param);
                            }


                        }catch (Exception e){
                            logger.info("---异步支付成功异常捕获成功--"+e.getMessage());
                            e.printStackTrace();
                            throw e;
                        }finally {
                            // 4、释放分布式锁 ================================================================
                            redisGlobalLock.unlock(key);
                        }
                    }else{
                        // 如果没有获取锁
                        Ensure.that(true).isTrue("17000706");
                    }

                    ProductOrderBean productOrderBean = null;

                    SerializeObject rateBean  = rateSettingsService.get(RateKeyEnum.RECHARGE.getKey());
                    BigDecimal fee = BigDecimal.ZERO;
                    if (rateBean != null && rateBean.getData() != null) {
                        JSONObject json = JSON.parseObject(JSONObject.toJSONString(rateBean.getData()));
                        int dayNum = billMapper.getTransactionNumForThisDay(trade.getMemberId(), CommonConstants.PayType.RECHARGE.getIndex());
                        int monthNum = billMapper.getTransactionNumForThisMonth(trade.getMemberId(), CommonConstants.PayType.RECHARGE.getIndex());
                        fee = fundRateConfig.getFee(json, rechargeAmount, dayNum, monthNum);
                    }

                    //收入明细
                    BillBean billBean = cn.ug.pay.utils.Common.getBillBean(trade);
                    billBean.setAmount(trade.getPayAmount());
                    billBean.setActualAmount(trade.getPayAmount());
                    billBean.setFee(fee);
                    billBean.setType(BillType.INCOME.getValue());
                    billBean.setTradeType(TradeType.ONLINE_RECHARGE.getValue());

                    //支出明细
                    BillBean billBean1 = cn.ug.pay.utils.Common.getBillBean(trade);
                    billBean1.setType(BillType.OUTLAY.getValue());


                    //更新订单状态
                    // 兼容ios CommonConstants.PayType.RECHARGE.getIndex() == trade.getType() 下版本去掉
                    if(CommonConstants.PayType.BUYING.getIndex() == trade.getType() || CommonConstants.PayType.RECHARGE.getIndex() == trade.getType()){
                        productOrderService.completePay(trade.getOrderId());
                        productOrderBean = productOrderService.findByOrderId(trade.getOrderId());
                        billBean1.setTradeType(TradeType.BUY_GOLD.getValue());
                        billBean1.setGoldPrice(productOrderBean.getGoldPrice());
                        SerializeObject<ProductFindBean> productFindBean = productService.queryProductById(productOrderBean.getProductId());
                        if(null == productFindBean || productFindBean.getCode() != ResultType.NORMAL) {
                            Ensure.that(true).isTrue("17000601");
                        }
                        ProductFindBean productBean = productFindBean.getData();
                        if (productBean.getRaiseGram().doubleValue() > 0) {
                            SerializeObject<List<DataDictionaryBean>> beans = dataDictionaryService.findListByClassification(GOLD_WEIGHT_RANGE, 1);
                            if (beans == null || beans.getData() == null || beans.getData().size() != 2) {
                                Ensure.that(true).isTrue("17000719");
                            }
                            double value0 = Double.parseDouble(beans.getData().get(0).getItemValue());
                            double value1 = Double.parseDouble(beans.getData().get(1).getItemValue());
                            double lowestQuota = 0;
                            if (value0 > value1) {
                                lowestQuota = productBean.getRaiseGram().doubleValue() * value1/100;
                            } else {
                                lowestQuota = productBean.getRaiseGram().doubleValue() * value0/100;
                            }
                            productService.addToRaiseGram(productBean.getId(), productOrderBean.getAmount());
                            double hadRaisedGram = productBean.getToRaiseGram().doubleValue()+productOrderBean.getAmount().doubleValue();
                            if (hadRaisedGram >= lowestQuota) {
                                productService.updateShelfState(productBean.getId(), 2);
                                SerializeObject<List<DataDictionaryBean>> dataBeans = dataDictionaryService.findListByClassification(cn.ug.msg.bean.status.CommonConstants.MsgType.PRODUCT_DOWN_SHELF.getName(), 1);
                                if (dataBeans != null && dataBeans.getData() != null) {
                                    List<DataDictionaryBean> data = dataBeans.getData();
                                    if (data != null && data.size() > 0) {
                                        for (DataDictionaryBean bean : data) {
                                            Sms sms = new Sms();
                                            sms.setPhone(bean.getItemValue());
                                            sms.setType(SmsType.SOLD_OUT);
                                            Map<String, String> paramMap = new HashMap<>(2);
                                            paramMap.put("produtName", productBean.getName());
                                            paramMap.put("hour", String.valueOf(Calendar.getInstance().get(Calendar.HOUR_OF_DAY)));
                                            sms.setParamMap(paramMap);
                                            amqpTemplate.convertAndSend(QUEUE_MSG_SMS_SEND, sms);
                                        }
                                    }
                                }
                            }
                        }

                        if (CommonConstants.PayType.RECHARGE.getIndex() == trade.getType()){
                            /**
                             * 微信服务号消息推送  账户余额不足充值
                             */
                            MemberAccount memberAccount = memberAccountMapper.findByMemberId(trade.getMemberId());
                            WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
                            wxMessageParamBean.setMemberId(trade.getMemberId());
                            //消息推送类型
                            wxMessageParamBean.setType(WxTemplateEnum.SUFFICIENT_NOT_RICH.getType());
                            WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.SUFFICIENT_NOT_RICH.getType());
                            WxNotifyData wxNotifyData = new WxNotifyData();

                            Map<String,WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
                            WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
                            first.setDataValue(wxTemplateEnum.getFirstData());
                            wxParamMap.put("first",first);

                            WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
                            keyword1.setDataValue(BigDecimalUtil.to2Point(trade.getAmount()).toString());
                            wxParamMap.put("keyword1",keyword1);

                            WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
                            keyword2.setDataValue(DateUtils.dateToStr(new Date(),DateUtils.patter));
                            wxParamMap.put("keyword2",keyword2);

                            WxNotifyData.TemplateDataAttr keyword3 = new WxNotifyData.TemplateDataAttr();
                            keyword3.setDataValue(memberAccount.getUsableAmount().toString());
                            wxParamMap.put("keyword3",keyword3);

                            WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
                            remark.setDataValue(wxTemplateEnum.getRemark());
                            wxParamMap.put("remark",remark);

                            wxNotifyData.setData(wxParamMap);
                            wxMessageParamBean.setTemplateData(wxNotifyData);
                            amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
                        }
                        if (CommonConstants.PayType.BUYING.getIndex() == trade.getType()){
                            WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
                            wxMessageParamBean.setMemberId(trade.getMemberId());
                            wxMessageParamBean.setType(WxTemplateEnum.PURCHASE_ACTIVITY_PRODUCT_SUCCEED.getType());
                            WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.PURCHASE_ACTIVITY_PRODUCT_SUCCEED.getType());
                            Map<String,WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
                            WxNotifyData wxNotifyData = new WxNotifyData();
                            WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
                            first.setDataValue(wxTemplateEnum.getFirstData().replace("{product}", productOrderBean.getProductName()));
                            wxParamMap.put("first", first);

                            WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
                            keyword1.setDataValue(productOrderBean.getOrderId());
                            wxParamMap.put("keyword1", keyword1);

                            WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
                            keyword2.setDataValue(BigDecimalUtil.to5Point(productOrderBean.getAmount()).toString());
                            wxParamMap.put("keyword2", keyword2);

                            WxNotifyData.TemplateDataAttr keyword3 = new WxNotifyData.TemplateDataAttr();
                            keyword3.setDataValue(BigDecimalUtil.to2Point(trade.getAmount()).toString());
                            wxParamMap.put("keyword3", keyword3);

                            WxNotifyData.TemplateDataAttr keyword4 = new WxNotifyData.TemplateDataAttr();
                            keyword4.setDataValue(BigDecimalUtil.to2Point(productOrderBean.getGoldPrice()).toString());
                            wxParamMap.put("keyword4", keyword4);

                            WxNotifyData.TemplateDataAttr keyword5 = new WxNotifyData.TemplateDataAttr();
                            keyword5.setDataValue(DateUtils.dateToStr(new Date(), DateUtils.patter));
                            wxParamMap.put("keyword5", keyword5);

                            WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
                            remark.setDataValue(wxTemplateEnum.getRemark());
                            wxParamMap.put("remark", remark);

                            wxNotifyData.setData(wxParamMap);
                            wxMessageParamBean.setTemplateData(wxNotifyData);
                            amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
                        }
                    }else if(CommonConstants.PayType.MALL.getIndex() == trade.getType()){
                        mallGoodsOrderService.succeedOrder(trade.getOrderId());
                        billBean1.setTradeType(TradeType.BUY_GOODS.getValue());
                    } else if (PayTypeEnum.GOLD_EXTRACTION.getType() == trade.getType() || PayTypeEnum.GOLD_CHANGE.getType() == trade.getType()) {
                        trade.setStatus(CommonConstants.PayStatus.YESPAY.getIndex());
                        tradeMapper.updatePayStatus(trade);
                        orderService.succeed(trade.getOrderId());
                        SerializeObject<OrderBean> order = orderService.getOrder(trade.getOrderId());
                        if (order != null && order.getData() != null) {
                            SerializeObject priceBean = priceService.currentGoldPrice();
                            BigDecimal goldPrice =BigDecimal.ZERO;
                            if (priceBean != null && priceBean.getData() != null) {
                                goldPrice = new BigDecimal(priceBean.getData().toString());
                            }
                            OrderBean orderBean = order.getData();
                            BillBean bill = new BillBean();
                            bill.setType(BillType.OUTLAY.getValue());
                            bill.setMemberId(trade.getMemberId());
                            bill.setOrderId(trade.getOrderId());
                            bill.setAmount(orderBean.getExpressFee());
                            bill.setActualAmount(orderBean.getExpressFee());
                            bill.setFee(BigDecimal.ZERO);
                            bill.setGoldPrice(goldPrice);
                            if (trade.getType() == PayTypeEnum.GOLD_EXTRACTION.getType()) {
                                bill.setTradeType(TradeType.GOLD_EXTRACTION_FREIGHT.getValue());
                                billService.save(bill);
                                bill.setAmount(orderBean.getProcessCost());
                                bill.setActualAmount(orderBean.getProcessCost());
                                bill.setFee(BigDecimal.ZERO);
                                bill.setTradeType(TradeType.GOLD_EXTRACTION_PROCESS_COST.getValue());
                                billService.save(bill);
                            } else if (trade.getType() == PayTypeEnum.GOLD_CHANGE.getType()) {
                                bill.setTradeType(TradeType.CHANGE_GOLD_FREIGHT.getValue());
                                billService.save(bill);
                                bill.setAmount(orderBean.getProcessCost());
                                bill.setActualAmount(orderBean.getProcessCost());
                                bill.setFee(BigDecimal.ZERO);
                                bill.setTradeType(TradeType.CHANGE_GOLD_PROCESS_COST.getValue());
                                billService.save(bill);
                            }

                            Msg msg = new Msg();
                            msg.setMemberId(trade.getMemberId());
                            msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.MALL_PAY_SUCCESS.getIndex());
                            Map<String, String> paramMap = new HashMap<>();
                            paramMap.put("goodsName", trade.getTitle());
                            paramMap.put("fundAmount",  fundAmount.toString());
                            msg.setParamMap(paramMap);
                            amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                        }
                    } else if (PayTypeEnum.MALL_NEW.getType() == trade.getType()) {
                        trade.setStatus(CommonConstants.PayStatus.YESPAY.getIndex());
                        tradeMapper.updatePayStatus(trade);
                        orderService.succeed(trade.getOrderId());
                        billBean1.setTradeType(TradeType.BUY_GOODS.getValue());
                        Msg msg = new Msg();
                        msg.setMemberId(trade.getMemberId());
                        msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.MALL_PAY_SUCCESS.getIndex());
                        Map<String, String> paramMap = new HashMap<>();
                        paramMap.put("goodsName", trade.getTitle());
                        paramMap.put("fundAmount",  fundAmount.toString());
                        msg.setParamMap(paramMap);
                        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                    } else if(PayTypeEnum.TBILL.getType() == trade.getType()){
                        billBean1.setTradeType(TradeType.BUY_GOLD.getValue());
                        PayTbill payTbill = payTbillService.selectByOrderNO(trade.getOrderId());
                        if (payTbill == null) {
                            return "";
                        }
                        billBean1.setGoldPrice(payTbill.getGoldPrice());
                        payTbillService.completePay(trade.getOrderId());

                        billBean.setTradeType(TradeType.BUY_GOLD.getValue());
                        billBean.setGoldPrice(payTbill.getGoldPrice());
                        SerializeObject<ProductFindBean> productFindBean = productService.queryProductById(payTbill.getProductId());
                        if(null == productFindBean || productFindBean.getCode() != ResultType.NORMAL) {
                            Ensure.that(true).isTrue("17000601");
                        }
                        int stock = productFindBean.getData().getStock() - payTbill.getTotalGram()/productFindBean.getData().getSpecification();
                        productService.updateStock(payTbill.getProductId(), stock);
                        // 微信推送消息  模板需要更动  新模板出来之后添加此功能
                    }else if (PayTypeEnum.ENTITY_GOLD_EXTRACTION.getType() == trade.getType()){
                        logger.info("---异步通知提金支付成功,订单号--"+trade.getOrderId());
                        ExtractGoldBaseBean extractGoldBaseBean = entityExtractGoldMapper.findByOrderNo(trade.getOrderId());
                        if (extractGoldBaseBean == null){
                            return "";
                        }
                        PayTbill payTbill = payTbillService.selectByOrderNO(extractGoldBaseBean.getTbillNo());
                        if (payTbill == null) {
                            return "";
                        }
                        billBean1.setTradeType(TradeType.GOLD_EXTRACTION.getValue());
                        billBean1.setGoldPrice(payTbill.getGoldPrice());
                        //支付完成
                        extractionGoldService.succeed(trade.getOrderId(),1);

                        //发送提金预约和提金成功短信
                        Msg subscribeMap = new Msg();
                        subscribeMap.setMemberId(trade.getMemberId());
                        subscribeMap.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.EXTRACTGOLD_SUBSCRIBE.getIndex());
                        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, subscribeMap);

                        Msg msg = new Msg();
                        msg.setMemberId(trade.getMemberId());
                        msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.EXTRACTGOLD_FINISH.getIndex());
                        Map<String, String> paramMap = new HashMap<>();
                        paramMap.put("productName", payTbill.getProductName());
                        paramMap.put("amount", amount.toString());
                        msg.setParamMap(paramMap);
                        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                        //发送提金预约微信通知
                        extractionGoldService.wxSubscribeSend(extractGoldBaseBean.getMemberId(),payTbill.getProductName(),
                                extractGoldBaseBean.getAddress(),extractGoldBaseBean.getFullname(),extractGoldBaseBean.getCellphone());
                    }else if (PayTypeEnum.EXTRACTION_OFFLINE.getType() == trade.getType()){
                        logger.info("---异步通知提金支付成功,订单号--"+trade.getOrderId());
                        ExtractGoldBaseBean extractGoldBaseBean = extractionOfflineMapper.findByOrderNo(trade.getOrderId());
                        if (extractGoldBaseBean == null){
                            return "";
                        }
                        PayTbill payTbill = payTbillService.selectByOrderNO(extractGoldBaseBean.getTbillNo());
                        if (payTbill == null) {
                            return "";
                        }
                        billBean1.setTradeType(TradeType.GOLD_EXTRACTION.getValue());
                        billBean1.setGoldPrice(payTbill.getGoldPrice());
                        //支付完成
                        extractionGoldService.succeed(trade.getOrderId(),2);

                        //发送提金预约和提金成功短信
                        Msg subscribeMap = new Msg();
                        subscribeMap.setMemberId(trade.getMemberId());
                        subscribeMap.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.EXTRACTGOLD_SUBSCRIBE.getIndex());
                        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, subscribeMap);

                        Msg msg = new Msg();
                        msg.setMemberId(trade.getMemberId());
                        msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.EXTRACTGOLD_FINISH.getIndex());
                        Map<String, String> paramMap = new HashMap<>();
                        paramMap.put("productName", payTbill.getProductName());
                        paramMap.put("amount", amount.toString());
                        msg.setParamMap(paramMap);
                        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                        //发送提金预约微信通知
                        extractionGoldService.wxSubscribeSend(extractGoldBaseBean.getMemberId(),payTbill.getProductName(),
                                extractGoldBaseBean.getAddress(),extractGoldBaseBean.getFullname(),extractGoldBaseBean.getCellphone());
                    }

                    logger.info("---------异步更新订单状态完成--------"+trade.getOrderId());

                    logger.info("---充值金额--"+trade.getPayAmount());
                    MemberAccount memberAccount = memberAccountMapper.findByMemberId(trade.getMemberId());
                    //更新收入明细
                    billBean.setTradeType(TradeType.ONLINE_RECHARGE.getValue());
                    billService.save(billBean);
                    if (billBean.getFee() != null && billBean.getFee().doubleValue() > 0) {
                        billBean.setId(UF.getRandomUUID());
                        billBean.setTradeType(TradeType.RECHARGE_FEE.getValue());
                        billBean.setAmount(billBean.getFee());
                        billBean.setActualAmount(billBean.getFee());
                        billBean.setFee(BigDecimal.ZERO);
                        billBean.setType(BillType.OUTLAY.getValue());
                        billService.save(billBean);
                    }
                    Msg rechargeMsg = new Msg();
                    rechargeMsg.setMemberId(trade.getMemberId());
                    rechargeMsg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.ACCOUNT_PAY_CHANGE.getIndex());
                    Map<String, String> rechargeParamMap = new HashMap<>();
                    rechargeParamMap.put("date", UF.getFormatDate("MM月dd日", UF.getDateTime()));
                    rechargeParamMap.put("changeAmount", BigDecimalUtil.to2Point(trade.getAmount()).toString());
                    rechargeParamMap.put("amount", BigDecimalUtil.to2Point(memberAccount.getUsableAmount()).toString());
                    rechargeMsg.setParamMap(rechargeParamMap);
                    logger.info("-----消息-------"+rechargeParamMap.toString());
                    amqpTemplate.convertAndSend(QUEUE_MSG_SEND, rechargeMsg);

                    //更新支出明细
                    if (PayTypeEnum.GOLD_EXTRACTION.getType() != trade.getType() && PayTypeEnum.GOLD_CHANGE.getType() != trade.getType()) {
                        billService.save(billBean1);
                    }
                    logger.info("---------收支明细已添加--------");

                    //添加资金账户支出变动消息队列
                    Msg msg = new Msg();
                    msg.setMemberId(trade.getMemberId());
                    msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.RECHARGE.getIndex());

                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("date", UF.getFormatDate("MM月dd日", UF.getDateTime()));
                    paramMap.put("amount", BigDecimalUtil.to2Point(trade.getPayAmount()).toString());
                    paramMap.put("usableAmount", BigDecimalUtil.to2Point(memberAccount.getUsableAmount()).toString());
                    paramMap.put("whetherPush","NO");
                    msg.setParamMap(paramMap);
                    logger.info("-----消息-------"+paramMap.toString());
                    amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);

                    //统计分析成功--充值
                    MemberAnalyseMsgParamBean analyse = new MemberAnalyseMsgParamBean();
                    analyse.setMemberId(trade.getMemberId());
                    analyse.setType(cn.ug.analyse.bean.status.CommonConstants.MemberAnalyseType.RECHARGE.getIndex());
                    amqpTemplate.convertAndSend(QUEUE_MEMBER_ANALYSE, analyse);

                    //统计分析成功--交易
                    MemberAnalyseMsgParamBean analyse1 = new MemberAnalyseMsgParamBean();
                    analyse1.setMemberId(trade.getMemberId());
                    analyse1.setType(cn.ug.analyse.bean.status.CommonConstants.MemberAnalyseType.TRADE.getIndex());
                    amqpTemplate.convertAndSend(QUEUE_MEMBER_ANALYSE, analyse1);
                    logger.info("-----统计分析-----");

                    //微信充值推送
                    //wxRecharge(trade.getMemberId(),trade.getType(),trade.getPayAmount(),memberAccount.getUsableAmount());

                    /**
                     * 微信服务号消息推送  收支变动
                     */
                   /* WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
                    wxMessageParamBean.setMemberId(trade.getMemberId());
                    wxMessageParamBean.setType(WxTemplateEnum.FUND_CHANGE.getType());
                    WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.FUND_CHANGE.getType());
                    WxNotifyData wxNotifyData = new WxNotifyData();

                    Map<String,WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
                    WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
                    first.setDataValue(wxTemplateEnum.getFirstData());
                    wxParamMap.put("first",first);

                    WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
                    keyword1.setDataValue(PayTypeEnum.getPayTypeEnum(trade.getType()).contains("新版本")?
                            cn.ug.msg.bean.status.CommonConstants.MsgType.MALL_PAY_SUCCESS.getName():PayTypeEnum.getPayTypeEnum(trade.getType()));
                    wxParamMap.put("keyword1",keyword1);

                    WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
                    keyword2.setDataValue(BigDecimalUtil.to2Point(trade.getAmount()).toString());
                    wxParamMap.put("keyword2",keyword2);

                    WxNotifyData.TemplateDataAttr keyword3 = new WxNotifyData.TemplateDataAttr();
                    keyword3.setDataValue(DateUtils.dateToStr(new Date(),DateUtils.patter));
                    wxParamMap.put("keyword3",keyword3);

                    WxNotifyData.TemplateDataAttr keyword4 = new WxNotifyData.TemplateDataAttr();
                    keyword4.setDataValue(BigDecimalUtil.to2Point(memberAccount.getUsableAmount()).toString());
                    wxParamMap.put("keyword4",keyword4);

                    WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
                    remark.setDataValue(wxTemplateEnum.getRemark());
                    wxParamMap.put("remark",remark);

                    wxNotifyData.setData(wxParamMap);
                    wxMessageParamBean.setTemplateData(wxNotifyData);
                    amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);*/

                //支付失败
                }else{
                    trades.setStatus(CommonConstants.PayStatus.FAIL.getIndex());
                    trades.setDescription(result.get("errormsg"));
                    trades.setErrCode(result.get("errorcode"));
                    if(CommonConstants.PayType.BUYING.getIndex() == trade.getType() || CommonConstants.PayType.RECHARGE.getIndex() == trade.getType()){
                        //订单关闭
                        productOrderService.updatePayStatus(ProductOrderPayStatus.FAIL.getValue(),serialNumber);
                        logger.info("----订单关闭----orderId="+serialNumber);
                        ProductOrderFee productOrderFee = productOrderFeeMapper.findByOrderId(serialNumber);
                        if(null != productOrderFee) {
                            if(StringUtils.isNotBlank(productOrderFee.getCouponRedId())) {
                                // 释放红包
                                couponRepertoryService.unlock(productOrderFee.getCouponRedId());
                            }
                            if(StringUtils.isNotBlank(productOrderFee.getCouponIncreaseId())) {
                                // 释放加息券
                                couponRepertoryService.unlock(productOrderFee.getCouponIncreaseId());
                            }
                        }
                        memberAccountService.orderExpireUnfreezeAmount(serialNumber);
                    } else if(CommonConstants.PayType.MALL.getIndex() == trade.getType()){
                        mallGoodsOrderService.failOrder(trade.getOrderId(), result.get("errormsg"));
                        memberAccountService.orderExpireUnfreezeAmount(serialNumber);
                    } else if (PayTypeEnum.GOLD_EXTRACTION.getType() == trade.getType() || PayTypeEnum.GOLD_CHANGE.getType() == trade.getType()) {
                        orderService.fail(trade.getOrderId(), result.get("errormsg"));
                        logger.info("解冻用户余额:" + serialNumber);
                        memberAccountService.orderExpireUnfreezeAmount(serialNumber);
                        SerializeObject<OrderBean> order = orderService.getOrder(trade.getOrderId());
                        if (order != null && order.getData() != null) {
                            OrderBean orderBean = order.getData();
                            MemberGold memberGold = memberGoldMapper.findByMemberId(trade.getMemberId());
                            if (memberGold != null) {
                                logger.info("商城订单信息：" + JSONObject.toJSONString(orderBean));
                                //            // 活期利息 = (T-1日利息)  2018-03-30决定活期利息不包含T日利息。T日利息对用户不可见
                                //            memberGoldBean.setInterestAmount(memberGoldBean.getInterestHistoryAmount());
                                //			// 本金 = T日本金 + (T-1日本金)
                                //			memberGoldBean.setPrincipalAmount(BigDecimalUtil.adds(memberGoldBean.getPrincipalNowAmount(), memberGoldBean.getPrincipalHistoryAmount()));
                                //			// 可用资产 = 本金 + 活期利息
                                //			memberGoldBean.setUsableAmount(BigDecimalUtil.adds(memberGoldBean.getPrincipalAmount(), memberGoldBean.getInterestAmount()));
                                //			// 总资产 = 可用资产 + 冻结资产
                                //			memberGoldBean.setTotalAmount(BigDecimalUtil.adds(memberGoldBean.getUsableAmount(), memberGoldBean.getFreezeAmount()));
                                //			// 转出总资产 += 支付总额
                                //			memberGoldBean.setTurnOutAmount(BigDecimalUtil.adds(memberGoldBean.getTurnOutAmount(), payAmount[0]));
                                BigDecimal interestHistoryAmount = memberGold.getInterestHistoryAmount();
                                interestHistoryAmount = BigDecimalUtil.add(interestHistoryAmount, orderBean.getInterestHistoryAmount());
                                memberGold.setInterestHistoryAmount(interestHistoryAmount);

                                BigDecimal principalNowAmount = memberGold.getPrincipalNowAmount();
                                principalNowAmount = BigDecimalUtil.add(principalNowAmount, orderBean.getPrincipalNowAmount());
                                memberGold.setPrincipalNowAmount(principalNowAmount);

                                BigDecimal principalHistoryAmount = memberGold.getPrincipalHistoryAmount();
                                principalHistoryAmount = BigDecimalUtil.add(principalHistoryAmount, orderBean.getPrincipalHistoryAmount());
                                memberGold.setPrincipalHistoryAmount(principalHistoryAmount);

                                memberGold.setInterestAmount(memberGold.getInterestHistoryAmount());
                                memberGold.setPrincipalAmount(BigDecimalUtil.adds(memberGold.getPrincipalNowAmount(), memberGold.getPrincipalHistoryAmount()));
                                memberGold.setUsableAmount(BigDecimalUtil.adds(memberGold.getPrincipalAmount(), memberGold.getInterestAmount()));
                                memberGold.setTotalAmount(BigDecimalUtil.adds(memberGold.getUsableAmount(), memberGold.getFreezeAmount()));
                                memberGold.setTurnOutAmount(BigDecimalUtil.subtract(memberGold.getTurnOutAmount(), orderBean.getTotalGram()));
                                memberGold.setFreezeGram(BigDecimalUtil.subtract(memberGold.getFreezeGram(), orderBean.getTotalGram()));
                                logger.info("解冻柚子黄金：" + JSONObject.toJSONString(memberGold));
                                memberGoldMapper.update(memberGold);
                            }
                        }
                    } else if (PayTypeEnum.MALL_NEW.getType() == trade.getType()) {
                        orderService.fail(trade.getOrderId(), result.get("errormsg"));
                        memberAccountService.orderExpireUnfreezeAmount(serialNumber);
                    } else if(PayTypeEnum.TBILL.getType() == trade.getType()) {
                        Map<String, Object> param = new HashMap<String, Object>();
                        param.put("orderNO", serialNumber);
                        param.put("status", TbillStatusEnum.FAIL.getStatus());
                        param.put("modifyTime", UF.getFormatDateTime(UF.getDateTime()));
                        param.put("readed", 0);
                        payTbillMapper.update(param);
                        memberAccountService.orderExpireUnfreezeAmount(serialNumber);
                        PayTbill payTbill = payTbillMapper.selectByOrderNO(trade.getSerialNumber());
                        if (payTbill != null && StringUtils.isNotBlank(payTbill.getCouponId())) {
                            couponRepertoryService.unlock(payTbill.getCouponId());
                        }
                        if (payTbill != null && StringUtils.isNotBlank(payTbill.getTicketId())) {
                            couponRepertoryService.unlock(payTbill.getTicketId());
                        }
                        if (payTbill != null && payTbill.getBeans() > 0) {
                            MemberAccount memberAccount = memberAccountMapper.findByMemberId(payTbill.getMemberId());
                            if (memberAccount != null) {
                                Map<String,Object> accountMap = new HashMap<String,Object>();
                                accountMap.put("id",memberAccount.getId());
                                accountMap.put("totalBean", memberAccount.getTotalBean()+payTbill.getBeans());
                                accountMap.put("usableBean", memberAccount.getUsableBean()+payTbill.getBeans());
                                memberAccountMapper.updateByPrimaryKeySelective(accountMap);
                            }
                        }
                    }else if (PayTypeEnum.ENTITY_GOLD_EXTRACTION.getType() == trade.getType()){
                        Map<String, Object> param = new HashMap<String, Object>();
                        param.put("orderNo", serialNumber);
                        param.put("status", 0);
                        entityExtractGoldMapper.update(param);
                        memberAccountService.orderExpireUnfreezeAmount(serialNumber);

                        Msg subscribeMap = new Msg();
                        subscribeMap.setMemberId(trades.getMemberId());
                        subscribeMap.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.EXTRACTGOLD_CANCEL.getIndex());
                        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, subscribeMap);

                        //微信推送
                        extractionGoldService.wxCloseSend(trade.getMemberId(),"支付失败");
                    }else if (PayTypeEnum.EXTRACTION_OFFLINE.getType() == trade.getType()){
                        Map<String, Object> param = new HashMap<String, Object>();
                        param.put("orderNo", serialNumber);
                        param.put("status", 0);
                        extractionOfflineMapper.update(param);
                        memberAccountService.orderExpireUnfreezeAmount(serialNumber);

                        Msg subscribeMap = new Msg();
                        subscribeMap.setMemberId(trades.getMemberId());
                        subscribeMap.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.EXTRACTGOLD_CANCEL.getIndex());
                        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, subscribeMap);

                        //微信推送
                        extractionGoldService.wxCloseSend(trade.getMemberId(),"支付失败");
                    }
                    //添加支付失败消息队列
                    Msg msg = new Msg();
                    msg.setMemberId(trade.getMemberId());
                    msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.PAY_FAIL.getIndex());

                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("date", UF.getFormatDate("MM月dd日", UF.getDateTime()));
                    paramMap.put("amount", trade.getAmount()+"");
                    paramMap.put("errorMsg", result.get("errormsg"));
                    msg.setParamMap(paramMap);
                    logger.info("-----消息-------"+paramMap.toString());
                    amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);

                }
                tradeMapper.updatePayStatus(trades);
                logger.info("---------finish--------");
                return CommonConstants.SUCCESS;
            }else{
                logger.info("该订单已支付------orderId="+serialNumber);
                return CommonConstants.SUCCESS;
            }
        }else{
            logger.info("----签名不通过----");
            return CommonConstants.FAIL;
        }
    }

    /**
     * 充值异步回调
     * @param yeePayParamBean
     * @return
     */
    public String yeePayRechargeAsyNotify(YeePayParamBean yeePayParamBean) {
        //将实体转化成Map
        Map<String, String>	result	= tZTService.decryptCallbackData(yeePayParamBean.getData(), yeePayParamBean.getEncryptkey());
        System.out.println("-----易宝支付异步返回参数----"+result.toString());
        if(!result.containsKey("customError")){
            String status = result.get("status");
            String orderId = result.get("requestno");
            String thirdNumber = result.get("yborderid");

            //验证该订单号是否支付完成
            Trade trade = tradeMapper.queryTradeByOrderId(orderId);
            Ensure.that(trade == null).isTrue("17000418");
            if(trade.getStatus() != CommonConstants.PayStatus.YESPAY.getIndex()){
                //更新交易数据
                Trade trades = new Trade();
                trades.setSerialNumber(orderId);
                trades.setThirdNumber(thirdNumber);
                //支付成功
                if("PAY_SUCCESS".equals(status)){
                    trades.setStatus(CommonConstants.PayStatus.YESPAY.getIndex());

                    MemberAccount memberAccount = null;
                    // 1、获取分布式锁防止重复调用 =====================================================
                    String key = PayDistributePrefix.PAY_MEMBER_ACCOUNT + trade.getMemberId();
                    if(redisGlobalLock.lock(key)) {
                        try{
                            memberAccount = memberAccountMapper.findByMemberId(trade.getMemberId());
                            //更新账户金额--年后加做分布式锁
                            updateMemberAccount(memberAccount,trade.getAmount());
                        }catch (Exception e){
                            throw  e;
                        }finally {
                            // 4、释放分布式锁 ================================================================
                            redisGlobalLock.unlock(key);
                        }
                    }else{
                        // 如果没有获取锁
                        Ensure.that(true).isTrue("17000706");
                    }

                    //更新收入明细
                    BillBean billBean = new BillBean();
                    billBean.setOrderId(trade.getOrderId());
                    billBean.setMemberId(trade.getMemberId());
                    billBean.setAmount(trade.getPayAmount());
                    billBean.setActualAmount(trade.getPayAmount().subtract(trade.getFee()));
                    billBean.setFee(trade.getFee());
                    billBean.setType(BillType.INCOME.getValue());
                    billBean.setTradeType(TradeType.ONLINE_RECHARGE.getValue());
                    billService.save(billBean);

                    if (billBean.getFee() != null && billBean.getFee().doubleValue() > 0) {
                        billBean.setId(UF.getRandomUUID());
                        billBean.setTradeType(TradeType.RECHARGE_FEE.getValue());
                        billBean.setAmount(billBean.getFee());
                        billBean.setActualAmount(billBean.getFee());
                        billBean.setFee(BigDecimal.ZERO);
                        billBean.setType(BillType.OUTLAY.getValue());
                        billService.save(billBean);
                    }

                    //发送短信、站内信--消息队列
                    //充值成功提醒
                    Msg msg = new Msg();
                    msg.setMemberId(trade.getMemberId());
                    msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.RECHARGE.getIndex());

                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("date", UF.getFormatDate("MM月dd日", UF.getDateTime()));
                    paramMap.put("amount", trade.getAmount()+"");
                    paramMap.put("usableAmount", memberAccount.getFundAmount().add(trade.getAmount())+"");
                    paramMap.put("whetherPush","YES");
                    msg.setParamMap(paramMap);

                    amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);

                    //统计分析成功
                    MemberAnalyseMsgParamBean analyse = new MemberAnalyseMsgParamBean();
                    analyse.setMemberId(trade.getMemberId());
                    analyse.setType(cn.ug.analyse.bean.status.CommonConstants.MemberAnalyseType.RECHARGE.getIndex());
                    amqpTemplate.convertAndSend(QUEUE_MEMBER_ANALYSE, analyse);
                    logger.info("-----充值统计分析-----");


                    /**
                     * 微信服务号消息推送
                     */
                    WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
                    wxMessageParamBean.setMemberId(trade.getMemberId());
                    //消息推送类型
                    wxMessageParamBean.setType(WxTemplateEnum.SUFFICIENT_NOT_RICH.getType());
                    WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.SUFFICIENT_NOT_RICH.getType());
                    WxNotifyData wxNotifyData = new WxNotifyData();

                    Map<String, WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
                    WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
                    first.setDataValue(wxTemplateEnum.getFirstData());
                    wxParamMap.put("first", first);

                    WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
                    keyword1.setDataValue(trade.getAmount().toString());
                    wxParamMap.put("keyword1", keyword1);

                    WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
                    keyword2.setDataValue(DateUtils.dateToStr(new Date(),DateUtils.patter));
                    wxParamMap.put("keyword2", keyword2);

                    WxNotifyData.TemplateDataAttr keyword3 = new WxNotifyData.TemplateDataAttr();
                    keyword3.setDataValue(memberAccount.getFundAmount().add(trade.getAmount())+"");
                    wxParamMap.put("keyword3", keyword3);

                    WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
                    remark.setDataValue(wxTemplateEnum.getRemark());
                    wxParamMap.put("remark", remark);

                    wxNotifyData.setData(wxParamMap);
                    wxMessageParamBean.setTemplateData(wxNotifyData);
                    amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
                //支付失败
                }else{
                    //发送短信、站内信--消息队列
                    //充值失败提醒
                    Msg msg = new Msg();
                    msg.setMemberId(trade.getMemberId());
                    msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.RECHARGE_FAIL.getIndex());

                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("date", UF.getFormatDate("MM月dd日", UF.getDateTime()));
                    paramMap.put("amount", trade.getAmount()+"");
                    paramMap.put("errorMsg", result.get("errormsg"));
                    msg.setParamMap(paramMap);

                    amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);

                    trades.setStatus(CommonConstants.PayStatus.FAIL.getIndex());
                    trades.setDescription(result.get("errormsg"));
                }
                tradeMapper.updatePayStatus(trades);
                return CommonConstants.SUCCESS;
            }else{
                logger.info("该订单已支付------orderId="+orderId);
                return CommonConstants.SUCCESS;
            }
        }else{
            logger.info("----签名不通过----");
            return CommonConstants.FAIL;
        }
    }

    /**
     * 提现异步回调
     * @param yeePayParamBean
     * @return
     */
    public String yeePayWithdrawAsyNotify(YeePayParamBean yeePayParamBean) {
        //将实体转化成Map
        Map<String, String>	result	= tZTService.decryptCallbackData(yeePayParamBean.getData(), yeePayParamBean.getEncryptkey());
        System.out.println("-----易宝支付提现异步返回参数----"+result.toString());
        if(!result.containsKey("customError")){
            String status = result.get("status");
            String orderId = result.get("requestno");
            String thirdNumber = result.get("yborderid");

            //验证该订单号是否退款完成
            WithdrawAuditBean withdrawAuditBean = withdrawService.findByOrderId(orderId);
            if(withdrawAuditBean.getStatus() == WithdrawStatus.PROCESSING.getValue()){
                //更新交易数据
                Trade trades = new Trade();
                trades.setOrderId(orderId);
                trades.setThirdNumber(thirdNumber);

                Msg msg = new Msg();

                // 1、获取分布式锁防止重复调用 =====================================================
                String key = PayDistributePrefix.PAY_MEMBER_ACCOUNT + withdrawAuditBean.getMemberId();
                if(redisGlobalLock.lock(key)) {
                    try{

                        //更新明细
                        BillBean billBean = new BillBean();
                        billBean.setOrderId(orderId);
                        billBean.setMemberId(withdrawAuditBean.getMemberId());
                        billBean.setAmount(withdrawAuditBean.getAmount());
                        billBean.setActualAmount(withdrawAuditBean.getActualAmount());
                        billBean.setFee(withdrawAuditBean.getFee());

                        //提现成功
                        if("WITHDRAW_SUCCESS".equals(status)){
                            logger.info("---提现成功---订单号="+orderId);

                            //将总金额和冻结金额扣除提现金额
                            memberAccountService.withdrawSuccess(withdrawAuditBean.getMemberId(), withdrawAuditBean.getAmount());
                            withdrawService.updateStatus(orderId, WithdrawStatus.SUCCESS.getValue(),null);
                            logger.info("------提现1--------");

                            //更新支出明细
                            billBean.setType(BillType.OUTLAY.getValue());
                            billBean.setTradeType(TradeType.ACCOUNT_WITHDRAWAL.getValue());
                            billMapper.updateTradeTypeByOrderId(orderId, TradeType.ACCOUNT_WITHDRAWAL.getValue(), BillType.OUTLAY.getValue());
                            logger.info("------提现2--------");
                            msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.WITHDRAW_SUCCESS.getIndex());

                            /**
                             * 微信服务号消息推送  提现成功
                             */
                            WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
                            wxMessageParamBean.setMemberId(withdrawAuditBean.getMemberId());
                            //消息推送类型
                            wxMessageParamBean.setType(WxTemplateEnum.EXTRACT_SUCCEED.getType());
                            WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.EXTRACT_SUCCEED.getType());
                            WxNotifyData wxNotifyData = new WxNotifyData();

                            Map<String,WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
                            WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
                            first.setDataValue(wxTemplateEnum.getFirstData());
                            wxParamMap.put("first",first);

                            WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
                            keyword1.setDataValue(withdrawAuditBean.getAddTimeString());
                            wxParamMap.put("keyword1",keyword1);

                            WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
                            keyword2.setDataValue(TradeType.ACCOUNT_WITHDRAWAL.getRemark());
                            wxParamMap.put("keyword2",keyword2);

                            WxNotifyData.TemplateDataAttr keyword3 = new WxNotifyData.TemplateDataAttr();
                            keyword3.setDataValue(withdrawAuditBean.getAmount().toString());
                            wxParamMap.put("keyword3",keyword3);

                            WxNotifyData.TemplateDataAttr keyword4 = new WxNotifyData.TemplateDataAttr();
                            keyword4.setDataValue(withdrawAuditBean.getFee().toString());
                            wxParamMap.put("keyword4",keyword4);

                            WxNotifyData.TemplateDataAttr keyword5 = new WxNotifyData.TemplateDataAttr();
                            keyword5.setDataValue(withdrawAuditBean.getActualAmount().toString());
                            wxParamMap.put("keyword5",keyword5);

                            WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
                            remark.setDataValue(wxTemplateEnum.getRemark());
                            wxParamMap.put("remark",remark);

                            wxNotifyData.setData(wxParamMap);
                            wxMessageParamBean.setTemplateData(wxNotifyData);
                            amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
                            //提现失败
                        }else{
                            //返还账户余额   金额+手续费
                            memberAccountService.withdrawFail(withdrawAuditBean.getMemberId(), withdrawAuditBean.getAmount(), withdrawAuditBean.getActualAmount());
                            billMapper.updateTradeTypeByOrderId(orderId, TradeType.ACCOUNT_WITHDRWAL_RETURN.getValue(), BillType.INCOME.getValue());
                            logger.info("---提现失败----订单号="+orderId+"-----errormsg"+result.get("errormsg"));
                            withdrawService.updateStatus(orderId, WithdrawStatus.FAIL.getValue(), result.get("errormsg"));
                            msg.setType(cn.ug.msg.bean.status.CommonConstants.MsgType.WITHDRAW_FAIL.getIndex());

                        }

                        //发送短信、站内信--消息队列
                        //提现成功或失败提醒
                        msg.setMemberId(withdrawAuditBean.getMemberId());
                        Map<String, String> paramMap = new HashMap<>();
                        paramMap.put("date", UF.getFormatDate("MM月dd日", UF.getDateTime()));
                        msg.setParamMap(paramMap);
                        logger.info("------提现3--------");
                        //消息队列发送
                        amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);
                    }catch(Exception e){
                        throw e;
                    }finally {
                        // 4、释放分布式锁 ================================================================
                        redisGlobalLock.unlock(key);
                    }
                }else {
                    // 如果没有获取锁
                    Ensure.that(true).isTrue("17000706");
                }
                return CommonConstants.SUCCESS;
            }else{
                logger.info("该订单已提现处理------orderId="+orderId);
                return CommonConstants.SUCCESS;
            }
        }else{
            logger.info("----签名不通过----");
            return CommonConstants.FAIL;
        }
    }
    /**
     * 更新账户--充值
     * @param memberAccount
     * @param amount
     */
    public void updateMemberAccount(MemberAccount memberAccount,BigDecimal amount){
        if(memberAccount != null){
            Map<String,Object> memberAccountMap = new HashMap<String,Object>();
            memberAccountMap.put("id",   memberAccount.getId());
            memberAccountMap.put("fundAmount", memberAccount.getFundAmount().add(amount).toString());
            memberAccountMap.put("usableAmount",memberAccount.getUsableAmount().add(amount).toString());
            memberAccountMapper.updateByPrimaryKeySelective(memberAccountMap);
        }
        logger.info("---账户余额更新完成（充值）---"+memberAccount.getMemberId());
    }

    private void wxRecharge(String memberId,Integer type,BigDecimal payAmount,BigDecimal UsableAmount){
        /**
         * 微信服务号消息推送  充值
         */
        WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
        wxMessageParamBean.setMemberId(memberId);
        wxMessageParamBean.setType(WxTemplateEnum.SUFFICIENT_NOT_RICH.getType());
        WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.SUFFICIENT_NOT_RICH.getType());
        WxNotifyData wxNotifyData = new WxNotifyData();

        Map<String,WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
        WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
        first.setDataValue(wxTemplateEnum.getFirstData());
        wxParamMap.put("first",first);

        WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
        keyword1.setDataValue(BigDecimalUtil.to2Point(payAmount).toString());
        wxParamMap.put("keyword1",keyword1);

        WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
        keyword2.setDataValue(DateUtils.dateToStr(new Date(),DateUtils.patter));
        wxParamMap.put("keyword2",keyword2);

        WxNotifyData.TemplateDataAttr keyword3 = new WxNotifyData.TemplateDataAttr();
        keyword3.setDataValue(BigDecimalUtil.to2Point(UsableAmount).toString());
        wxParamMap.put("keyword3",keyword3);

        WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
        remark.setDataValue(wxTemplateEnum.getRemark());
        wxParamMap.put("remark",remark);

        wxNotifyData.setData(wxParamMap);
        wxMessageParamBean.setTemplateData(wxNotifyData);
        amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
    }

    public static void main(String[] args) {
        BigDecimal a = new BigDecimal(2L);
        BigDecimal b = new BigDecimal(1l);
        System.out.println(a.compareTo(b));
        System.out.println(a.subtract(b));
    }
}
